package com.ruoyi.web.cp.service.cp;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.utils.NumberUtils;
import com.ruoyi.web.core.config.ConfigLoader;
import com.ruoyi.web.cp.domain.rm.CpAo5;
import com.ruoyi.web.cp.service.WinxinService;
import com.ruoyi.web.mapper.CpAo5Mapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.File;
import java.util.*;
import java.util.stream.IntStream;

@Slf4j
@Service
public class Ao5FiveFourStarService {
    public final static List<Integer> codes = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 0);
    @Value("${ao5.path:C:\\rm\\ao5\\}")
    private String ao5Path;
    @Autowired
    private CpAo5Mapper cpAo5Mapper;
    @Autowired
    private ConfigLoader configLoader;
    @Autowired
    private WinxinService winxinService;

    public Map<String, Object> checkFourCode(boolean isGenerate) {
        List<CpAo5> codes = cpAo5Mapper.selectTop5(null);
        if (isGenerate) {
            do {
                generateFourCode();

                File path = new File(ao5Path + "四星");
                File[] files = path.listFiles();
                if (files == null || files.length == 0) {
                    return null;
                }

                // 检查codes[0]和codes[1]中的front或back是否有相同文件名
                if (codes.size() >= 2) {
                    CpAo5 code0 = codes.get(0);
                    CpAo5 code1 = codes.get(1);

                    // 计算code0的front
                    Set<String> front0 = new HashSet<>();
                    String codeStr0 = code0.getPreDrawCode().replace(",", "");
                    for (File file : files) {
                        String strs = FileUtil.readString(file, "utf8");
                        if (!strs.contains(codeStr0.substring(0, 4))) {
                            front0.add(file.getName());
                        }
                    }

                    // 计算code0的back
                    Set<String> back0 = new HashSet<>();
                    for (File file : files) {
                        String strs = FileUtil.readString(file, "utf8");
                        if (!strs.contains(codeStr0.substring(1, 5))) {
                            back0.add(file.getName());
                        }
                    }

                    // 计算code1的front
                    Set<String> front1 = new HashSet<>();
                    String codeStr1 = code1.getPreDrawCode().replace(",", "");
                    for (File file : files) {
                        String strs = FileUtil.readString(file, "utf8");
                        if (!strs.contains(codeStr1.substring(0, 4))) {
                            front1.add(file.getName());
                        }
                    }

                    // 计算code1的back
                    Set<String> back1 = new HashSet<>();
                    for (File file : files) {
                        String strs = FileUtil.readString(file, "utf8");
                        if (!strs.contains(codeStr1.substring(1, 5))) {
                            back1.add(file.getName());
                        }
                    }

                    // 检查是否有交集
                    boolean hasCommonFront = !Collections.disjoint(front0, front1);
                    boolean hasCommonBack = !Collections.disjoint(back0, back1);

                    // 如果front或back有相同文件名，则停止生成
                    if (hasCommonFront || hasCommonBack) {
                        break;
                    }
                }
            } while (true);
        }


        File path = new File(ao5Path + "四星");
        File[] files = path.listFiles();
        if (files == null || files.length == 0) {
            return null;
        }

        Map<String, Object> result = new LinkedHashMap<>();

        for (int j = 0; j < codes.size(); j++) {
            JSONObject data = new JSONObject();
            data.put("code", codes.get(j).getPreDrawCode());

            JSONArray front = new JSONArray();
            String code = codes.get(j).getPreDrawCode().replace(",", "");
            for (int i = 0; i < files.length; i++) {
                File file = files[i];
                String strs = FileUtil.readString(file, "utf8");
                if (!strs.contains(code.substring(0, 4))) {
                    front.add(file.getName());
                }
            }
            data.put("front", front);

            JSONArray back = new JSONArray();
            for (int i = 0; i < files.length; i++) {
                File file = files[i];
                String strs = FileUtil.readString(file, "utf8");
                if (!strs.contains(code.substring(1, 5))) {
                    back.add(file.getName());
                }
            }
            data.put("back", back);
            result.put(codes.get(j).getPreDrawIssue(), data);
        }
        return result;
    }

    public Map<String, Object> checkFiveCode(boolean isGenerate) {
        List<CpAo5> codes = cpAo5Mapper.selectTopX(null, 20);
        int count = 0;
        if (isGenerate) {
            Map<String, String> fileContentCache = new HashMap<>(); // 添加文件内容缓存
            do {
                generateFiveCode();

                File path = new File(ao5Path + "五星");
                File[] files = path.listFiles();
                if (files == null || files.length == 0) {
                    return null;
                }

                // 清空并预加载文件内容缓存
                fileContentCache.clear();
                for (File file : files) {
                    fileContentCache.put(file.getName(), FileUtil.readString(file, "utf8"));
                }

                // 检查codes[0]和codes[1]中是否有相同文件名
                if (codes.size() >= 2) {
                    CpAo5 code0 = codes.get(0);
                    CpAo5 code1 = codes.get(1);

                    // 计算code0
                    Set<String> result0 = new HashSet<>();
                    String codeStr0 = code0.getPreDrawCode().replace(",", "");
                    for (File file : files) {
                        String strs = fileContentCache.get(file.getName());
                        if (!strs.contains(codeStr0)) {
                            result0.add(file.getName());
                        }
                    }

                    // 计算code1
                    Set<String> result1 = new HashSet<>();
                    String codeStr1 = code1.getPreDrawCode().replace(",", "");
                    for (File file : files) {
                        String strs = fileContentCache.get(file.getName());
                        if (!strs.contains(codeStr1)) {
                            result1.add(file.getName());
                        }
                    }

                    // 修正判断逻辑: 检查是否有交集
//                    boolean hasCommonFiles = !Collections.disjoint(result0, result1);
                    boolean hasCommonFiles = CollUtil.isEmpty(result0) && CollUtil.isEmpty(result1);

                    if (hasCommonFiles) {
                        break;
                    }
                    count++;
                    System.out.println(count);
                }
            } while ((count < 50));
        }


        File path = new File(ao5Path + "五星");
        File[] files = path.listFiles();
        if (files == null || files.length == 0) {
            return null;
        }

        Map<String, Object> result = new LinkedHashMap<>();

        for (int j = 0; j < codes.size(); j++) {
            CpAo5 cpAo5 = codes.get(j);
            JSONObject data = buildFiveCodeData(cpAo5, files);
            result.put(cpAo5.getPreDrawIssue(), data);
        }
        result.put("count", count);
        return result;
    }

    private JSONObject buildFiveCodeData(CpAo5 cpAo5, File[] files) {
        JSONObject data = new JSONObject();
        data.put("code", cpAo5.getPreDrawCode());

        JSONArray all = new JSONArray();
        String code = cpAo5.getPreDrawCode().replace(",", "");
        for (File file : files) {
            String strs = FileUtil.readString(file, "utf8");
            if (!strs.contains(code)) {
                all.add(file.getName());
            }
        }
        data.put("all", all);
        return data;
    }


    public String getFourCode(String name) {
        return FileUtil.readString(ao5Path + "四星\\200_" + name + ".txt", "utf8");
    }

    private void generateFourCode() {
        for (int i = 0; i < 100; i++) {
            List<String> combinations = new ArrayList<>();
            // 生成所有4位数组合
            NumberUtils.generateCombinations(codes, "", 4, combinations);
            // 打乱顺序
            Collections.shuffle(combinations);

            // 去除最后200个元素
            if (combinations.size() > 200) {
                combinations = combinations.subList(0, combinations.size() - 200);
            }
            // 打印结果
            FileUtil.writeString(CollUtil.join(combinations, ";"), ao5Path + "四星\\200_" + i + ".txt", "utf8");
        }
    }

    private void generateFiveCode() {
        // 缓存全量5位数组合，只生成一次
        List<String> allCombinations = getFiveCombinations();
        long startTime1 = System.currentTimeMillis();
        // 使用并行流并发执行
        IntStream.range(0, 100).parallel().forEach(i -> {
            long startTime = System.currentTimeMillis();

            // 创建当前线程的组合副本
            List<String> currentCombinations = new ArrayList<>(allCombinations);

            // 打乱顺序
            Collections.shuffle(currentCombinations);

            // 保留前2000个元素（修正原代码逻辑错误）
            List<String> selected = currentCombinations.subList(0, currentCombinations.size() - 2000);

            // 写入文件
            FileUtil.writeString(CollUtil.join(selected, ";"),
                    ao5Path + "五星\\2000_" + i + ".txt", "utf8");
//            FileUtil.writeString(CollUtil.join(selected, ";"),
//                    "C:\\rm\\ao5\\五星1\\2000_" + i + ".txt", "utf8");

        });
    }

    public static void main(String[] args) {
        Ao5FiveFourStarService service = new Ao5FiveFourStarService();
        service.generateFiveCode();
    }


    public String getCodes(String codes) {
        String[] codeArray = codes.split(",");
        if (codeArray.length < 2) {
            throw new IllegalArgumentException("codes must contain at least 2 elements");
        }

        // 缓存组合结果，避免重复生成
        List<String> combinations = getFiveCombinations();

        String path1 = ao5Path + "五星" + File.separator + "2000_" + codeArray[0] + ".txt";
        String path2 = ao5Path + "五星" + File.separator + "2000_" + codeArray[1] + ".txt";

        String str1 = FileUtil.readString(path1, "utf8");
        String str2 = FileUtil.readString(path2, "utf8");

        Set<String> codes2Set = new HashSet<>(Arrays.asList(str2.split(";")));
        Set<String> combinationsSet = new HashSet<>(combinations);

        combinationsSet.removeAll(codes2Set);

        String[] codes1 = str1.split(";");
        List<String> result = new ArrayList<>();
        Set<String> subtractSet = new HashSet<>(combinationsSet);

        for (String code : codes1) {
            if (!subtractSet.contains(code)) {
                result.add(code);
            }
        }

        return CollUtil.join(result, ";");
    }

    // 添加组合缓存
    private List<String> fiveCombinationsCache = null;

    private List<String> getFiveCombinations() {
        if (fiveCombinationsCache == null) {
            fiveCombinationsCache = new ArrayList<>();
            NumberUtils.generateCombinations(this.codes, "", 5, fiveCombinationsCache);
        }
        return fiveCombinationsCache;
    }

    public String getCodes2() {
        File path = new File(ao5Path + "五星");
        File[] files = path.listFiles();
        if (files == null || files.length == 0) {
            return null;
        }

        // 只获取一次全量组合，并缓存
        List<String> combinations = getFiveCombinations();
        Set<String> result = new HashSet<>();

        // 收集所有已使用的号码
        for (File file : files) {
            Set<String> combinationsSet = new HashSet<>(combinations);
            String strs = FileUtil.readString(file, "utf8");
            String[] split = strs.split(";");
            combinationsSet.removeAll(Arrays.asList(split));
            result.addAll(combinationsSet);
        }

        // 一次性计算差集
        if (CollUtil.isEmpty(result)) {
            return "no result";
        }

        return CollUtil.join(result, ";");
    }

    public String check2000LastCode() {
        CpAo5 ao5 = cpAo5Mapper.selectLatest();

        File path = new File(ao5Path + "五星");
        File[] files = path.listFiles();
        if (files == null || files.length == 0) {
            return null;
        }

        Map<String, Object> result = new LinkedHashMap<>();

        JSONObject data = buildFiveCodeData(ao5, files);
        if (CollUtil.isEmpty(data.getJSONArray("all"))) {
            winxinService.sendQlMsg("e4c19ce3-c235-4e34-a3c2-efb70f551919", ao5.getPreDrawIssue() + " 2000为空");
        }
        return data.toJSONString();
    }
}
